{
  "cells": [
    {
      "cell_type": "raw",
      "id": "10238e62-3465-4973-9279-606cbb7ccf16",
      "metadata": {
        "vscode": {
          "languageId": "raw"
        }
      },
      "source": [
        "---\n",
        "sidebar_label: Tavily Search\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a6f91f20",
      "metadata": {},
      "source": [
        "# TavilySearch\n",
        "\n",
        "[Tavily](https://tavily.com/) is a search engine built specifically for AI agents (LLMs), delivering real-time, accurate, and factual results at speed. Tavily offers two key endpoints, one of which being Search, which provides search results tailored for LLMs and RAG.\n",
        "\n",
        "This guide provides a quick overview for getting started with the Tavily [tool](/docs/integrations/tools/). For a complete breakdown of the Tavily tool, you can find more detailed documentation in the [API reference](https://v03.api.js.langchain.com/modules/_langchain_tavily.html).\n",
        "\n",
        "## Overview\n",
        "\n",
        "### Integration details\n",
        "\n",
        "| Class | Package | [PY support](https://python.langchain.com/docs/integrations/tools/tavily_search/) | Package latest |\n",
        "| :--- | :--- | :---: | :---: |\n",
        "| [TavilySearch](https://api.js.langchain.com/classes/_langchain_tavily.TavilySearch.html) | [`@langchain/tavily`](https://www.npmjs.com/package/@langchain/tavily) | ✅ |  ![NPM - Version](https://img.shields.io/npm/v/@langchain/tavily?style=flat-square&label=%20&) |\n",
        "\n",
        "## Setup\n",
        "\n",
        "The integration lives in the `@langchain/tavily` package, which you can install as shown below:\n",
        "\n",
        "```{=mdx}\n",
        "import IntegrationInstallTooltip from \"@mdx_components/integration_install_tooltip.mdx\";\n",
        "import Npm2Yarn from \"@theme/Npm2Yarn\";\n",
        "\n",
        "<IntegrationInstallTooltip></IntegrationInstallTooltip>\n",
        "\n",
        "<Npm2Yarn>\n",
        "  @langchain/tavily @langchain/core\n",
        "</Npm2Yarn>\n",
        "```\n",
        "\n",
        "### Credentials\n",
        "\n",
        "Set up an API key [here](https://app.tavily.com) and set it as an environment variable named `TAVILY_API_KEY`.\n",
        "\n",
        "```typescript\n",
        "process.env.TAVILY_API_KEY = \"YOUR_API_KEY\"\n",
        "```\n",
        "\n",
        "It's also helpful (but not needed) to set up [LangSmith](https://smith.langchain.com/) for best-in-class observability:\n",
        "\n",
        "```typescript\n",
        "process.env.LANGSMITH_TRACING=\"true\"\n",
        "process.env.LANGSMITH_API_KEY=\"your-api-key\"\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1c97218f-f366-479d-8bf7-fe9f2f6df73f",
      "metadata": {},
      "source": [
        "## Instantiation\n",
        "\n",
        "You can import and instantiate an instance of the `TavilySearch` tool like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "8b3ddfe9-ca79-494c-a7ab-1f56d9407a64",
      "metadata": {},
      "outputs": [],
      "source": [
        "import { TavilySearch } from \"@langchain/tavily\";\n",
        "\n",
        "const tool = new TavilySearch({\n",
        "  maxResults: 5,\n",
        "  topic: \"general\",\n",
        "  // includeAnswer: false,\n",
        "  // includeRawContent: false,\n",
        "  // includeImages: false,\n",
        "  // includeImageDescriptions: false,\n",
        "  // searchDepth: \"basic\",\n",
        "  // timeRange: \"day\",\n",
        "  // includeDomains: [],\n",
        "  // excludeDomains: [],\n",
        "});"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74147a1a",
      "metadata": {},
      "source": [
        "## Invocation\n",
        "\n",
        "### [Invoke directly with args](/docs/concepts/tools)\n",
        "\n",
        "The Tavily search tool accepts the following arguments during invocation:\n",
        "\n",
        "* `query` (required): A natural language search query\n",
        "\n",
        "* The following arguments can also be set during invocation : `includeImages`, `searchDepth` , `timeRange`, `includeDomains`, `excludeDomains`, `includeImages`.\n",
        "\n",
        "* For reliability and performance reasons, certain parameters that affect response size cannot be modified during invocation: `includeAnswer` and `includeRawContent`. These limitations prevent unexpected context window issues and ensure consistent results."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "65310a8b-eb0c-4d9e-a618-4f4abe2414fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "await tool.invoke({\n",
        "  query: \"what is the current weather in SF?\"\n",
        "});"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6e73897",
      "metadata": {},
      "source": [
        "### [Invoke with ToolCall](/docs/concepts/tools)\n",
        "\n",
        "We can also invoke the tool with a model-generated `ToolCall`, in which case a `ToolMessage` will be returned:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f90e33a7",
      "metadata": {},
      "outputs": [],
      "source": [
        "// This is usually generated by a model, but we'll create a tool call directly for demo purposes.\n",
        "const modelGeneratedToolCall = {\n",
        "  args: {\n",
        "    query: \"what is the current weather in SF?\"\n",
        "  },\n",
        "  id: \"1\",\n",
        "  name: tool.name,\n",
        "  type: \"tool_call\",\n",
        "}\n",
        "\n",
        "await tool.invoke(modelGeneratedToolCall)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "659f9fbd-6fcf-445f-aa8c-72d8e60154bd",
      "metadata": {},
      "source": [
        "## Chaining\n",
        "\n",
        "We can use our tool in a chain by first binding it to a [tool-calling model](/docs/how_to/tool_calling/) and then calling it:\n",
        "\n",
        "```{=mdx}\n",
        "import ChatModelTabs from \"@theme/ChatModelTabs\";\n",
        "\n",
        "<ChatModelTabs customVarName=\"llm\" />\n",
        "```\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "af3123ad-7a02-40e5-b58e-7d56e23e5830",
      "metadata": {},
      "outputs": [],
      "source": [
        "// @lc-docs-hide-cell\n",
        "\n",
        "import { ChatOpenAI } from \"@langchain/openai\"\n",
        "\n",
        "const llm = new ChatOpenAI({\n",
        "  model: \"gpt-4o\",\n",
        "  temperature: 0,\n",
        "})"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fdbf35b5-3aaf-4947-9ec6-48c21533fb95",
      "metadata": {},
      "outputs": [],
      "source": [
        "import { HumanMessage } from \"@langchain/core/messages\";\n",
        "import { ChatPromptTemplate } from \"@langchain/core/prompts\";\n",
        "import { RunnableLambda } from \"@langchain/core/runnables\";\n",
        "\n",
        "const prompt = ChatPromptTemplate.fromMessages(\n",
        "  [\n",
        "    [\"system\", \"You are a helpful assistant.\"],\n",
        "    [\"placeholder\", \"{messages}\"],\n",
        "  ]\n",
        ")\n",
        "\n",
        "const llmWithTools = llm.bindTools([tool]);\n",
        "\n",
        "const chain = prompt.pipe(llmWithTools);\n",
        "\n",
        "const toolChain = RunnableLambda.from(\n",
        "  async (userInput: string, config) => {\n",
        "    const humanMessage = new HumanMessage(userInput,);\n",
        "    const aiMsg = await chain.invoke({\n",
        "      messages: [new HumanMessage(userInput)],\n",
        "    }, config);\n",
        "    const toolMsgs = await tool.batch(aiMsg.tool_calls, config);\n",
        "    return chain.invoke({\n",
        "      messages: [humanMessage, aiMsg, ...toolMsgs],\n",
        "    }, config);\n",
        "  }\n",
        ");\n",
        "\n",
        "const toolChainResult = await toolChain.invoke(\"what is the current weather in sf?\");"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9ac188a2",
      "metadata": {},
      "outputs": [],
      "source": [
        "const { tool_calls, content } = toolChainResult;\n",
        "\n",
        "console.log(\"AIMessage\", JSON.stringify({\n",
        "  tool_calls,\n",
        "  content,\n",
        "}, null, 2));"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "573fb391",
      "metadata": {},
      "source": [
        "## Agents\n",
        "\n",
        "For guides on how to use LangChain tools in agents, see the [LangGraph.js](https://langchain-ai.github.io/langgraphjs/how-tos/#tool-calling) docs."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ac8146c",
      "metadata": {},
      "source": [
        "## API reference\n",
        "\n",
        "For detailed documentation of all Tavily Search API features and configurations head to the API reference: \n",
        "\n",
        "https://docs.tavily.com/documentation/api-reference/endpoint/search"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d221c68a",
      "metadata": {},
      "source": [
        "## Related\n",
        "\n",
        "* Tool [conceptual guide](https://js.langchain.com/docs/concepts/tools/)\n",
        "\n",
        "* Tool [how-to guides](https://js.langchain.com/docs/how_to/#tools)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "TypeScript",
      "language": "typescript",
      "name": "tslab"
    },
    "language_info": {
      "codemirror_mode": {
        "mode": "typescript",
        "name": "javascript",
        "typescript": true
      },
      "file_extension": ".ts",
      "mimetype": "text/typescript",
      "name": "typescript",
      "version": "3.7.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
